lgssystem

Define and solve models for LGS systems

source

LGSSystem

 LGSSystem (system:str, fixed_params:dict={})

LGSSystem creates numerical models for the chosen laser guide star atomic system.

Type Default Details
system str Name of the atomic system to be loaded from file
fixed_params dict {} Values for system parameters that will be held fixed

source

LGSSystem.builtins

 LGSSystem.builtins ()

List the available LGS systems:

LGSSystem.builtins()
['NaD1', 'Na330', 'NaD2', 'NaD2_Repump', 'NaD1_Toy']

source

LGSSystem.diagram

 LGSSystem.diagram (name:str|pathlib.Path, kind='Toy')

Draw a level diagram for the system of the specified kind.

Type Default Details
name str | pathlib.Path Name of built-in LGS system definition, or directory of supplied system
kind str Toy “Toy” to show level diagram and pumped transitions, “ToScale” to show hyperfine structure to scale, “NotToScale” to show unscaled hf structure
LGSSystem.diagram("Na330", "Toy")

LGSSystem.diagram("Na330", "ToScale")

LGSSystem.diagram("Na330", "NotToScale")


source

LGSSystem.info

 LGSSystem.info (name:str|pathlib.Path)

Display information about LGS system name.

Type Details
name str | pathlib.Path Name of built-in LGS system definition, or directory of supplied system
LGSSystem.info("NaD2_Repump")

Atomic levels

\(\text{3S}_{\frac{1}{2}}\), \(\text{3P}_{\frac{3}{2}}\)

Pump transitions

  1. \(\text{3S}_{\frac{1}{2}}\land F=1\to \text{3P}_{\frac{3}{2}}\)
  2. \(\text{3S}_{\frac{1}{2}}\land F=2\to \text{3P}_{\frac{3}{2}}\)

Transition wavelengths

  • \(\text{3P}_{\frac{3}{2}}\to \text{3S}_{\frac{1}{2}}\): 589.158 nm

Substructure

  • Hyperfine structure included
  • Zeeman structure included
  • 24 total sublevels

Density matrix elements

  • All populations included
  • All Zeeman coherences (between same level and same F) included
  • All hyperfine coherences (between same level and different F) neglected
  • Optical coherences (between different levels) included for pump transitions only
  • 374 total density matrix elements

Input parameters

  • BeamTransitRatePerS
  • BFieldG
  • MagneticAzimuthDegrees
  • MagneticZenithDegrees
  • RecoilParameter
  • SDampingCollisionRatePerS
  • TemperatureK
  • VccRatePerS
  • DetuningHz1
  • DetuningHz2
  • EllipticityDegrees1
  • EllipticityDegrees2
  • IntensitySI1
  • IntensitySI2
  • LaserWidthHz1
  • LaserWidthHz2
  • PolarizationAngleDegrees1
  • PolarizationAngleDegrees2

Load a “toy” (no angular momentum) model LGS system and fix values for most of the parameters:

lgs = LGSSystem(
    'NaD1_Toy',
    fixed_params={'EllipticityDegrees1': 45.0,
                  'PolarizationAngleDegrees1': 0,
                  'DetuningHz1': 0,
                  'LaserWidthHz1': 10.0e6,
                  'BFieldG': 0.5,
                  'MagneticZenithDegrees': 45.0,
                  'MagneticAzimuthDegrees': 45.0,
                  'SDampingCollisionRatePerS': 4e3,
                  'BeamTransitRatePerS': 1e2,
                  'VccRatePerS': 3e4,
                  'TemperatureK': 2e2,
                  'RecoilParameter': 1,
                 }
)

The only remaining parameter is the laser intensity. Here the value 1 indicates that the parameter is a scalar quantity:

lgs.parameters
Parameters({IntensitySI1: 1})

Define a value for the intensity to use for the following examples:

mu = Mu(IntensitySI1=46.)

source

LGSSystem.operator

 LGSSystem.operator (vg:pylgs.velocitygroups.VelocityGroups)

The evolution operatior for the system, given the VelocityGroups vg.

Type Details
vg VelocityGroups VelocityGroups specification
Returns Operator

Form the operator with the example VelocityGroups:

op = lgs.operator(vg)

The operator operates on vectors from the \(2\times4\) (velocity \(\times\) density matrix) product vector space:

op.source
{Atomic velocity(2) ⨉ Density matrix (source)(4)}

And returns a vector from the same space:

op.range
{Atomic velocity (range)(2) ⨉ Density matrix (range)(4)}

Substitute the free parameter values into the operator and write it explicitly as a block matrix, with \(2\times2\) blocks for the velocity space, each block being \(4\times4\) on the density matrix space:

to_matrix(op, mu=mu).toarray()/1e6
array([[  0.015 ,     0   , -2.6e+01, -6.1e+01,  -0.015 ,     0   ,     0   ,     0   ],
       [    0   ,  6.2e+01, -6.1e+03,     0   ,     0   ,     0   ,     0   ,     0   ],
       [ 1.3e+01,  6.1e+03,  6.2e+01, -1.3e+01,     0   ,     0   ,     0   ,     0   ],
       [    0   ,     0   ,  2.6e+01,  6.1e+01,     0   ,     0   ,     0   ,  -0.015 ],
       [ -0.015 ,     0   ,     0   , -0.0016 ,   0.015 ,     0   , -2.6e+01, -6.1e+01],
       [    0   ,     0   ,     0   ,     0   ,     0   ,  6.2e+01,  6.1e+03,     0   ],
       [    0   ,     0   ,     0   ,     0   ,  1.3e+01, -6.1e+03,  6.2e+01, -1.3e+01],
       [    0   ,     0   ,     0   ,  -0.015 ,     0   ,     0   ,  2.6e+01,  6.1e+01]])

source

LGSSystem.rhs

 LGSSystem.rhs (vg:pylgs.velocitygroups.VelocityGroups)

The right-hand side vector for this system given the VelocityGroups vg.

Type Details
vg VelocityGroups VelocityGroups specification
Returns VectorArray

Form the right-hand side VectorArray:

vec = lgs.rhs(vg)

The vector is in the \(2\times4\) (velocity \(\times\) density matrix) product vector space:

vec.space
{Atomic velocity (range)(2) ⨉ Density matrix (range)(4)}
vec.space.shape
(2, 4)

Write as a flattened 1D vector:

vec.to_numpy()
array([[  5e+01 ,     0   ,     0   ,     0   ,   5e+01 ,     0   ,     0   ,     0   ]])
test_array('core', 'rhs', _)
test_array('core', '_initial_dm', _)

source

LGSSystem.stationary_model

 LGSSystem.stationary_model
                             (vg:Union[int,Iterable,pylgs.velocitygroups.V
                             elocityGroups]=6)

Return a pyMOR StationaryModel for the steady state cw LGS system.

Type Default Details
vg Union 6 Specification of velocity groups
Returns StationaryModel Model for the steady-state LGS system

An integer can be supplied for vg to get that many evenly spaced velocity groups:

model = lgs.stationary_model(vg=30)

Solve the model and calculate the return flux by supplying values for all free parameters:

model.total_flux({'IntensitySI1': 1e3}).item()
52423.693460667244

Solve the model and return the steady-state density matrix:

sol = model.solve({'IntensitySI1': 1e3})

The solution can be visualized in several ways. Plot the flux for each velocity bin:

model.flux(sol).visualize()

Plot the real and imaginary parts of the density-matrix elements for each velocity bin:

sol.visualize()

Plot just the level populations:

model.level_population(sol).visualize()

Plot the total atomic population:

model.population(sol).visualize()

Note that the above visualizations plot the contribution to the quantity from each velocity group. If the velocity groups are not all of the same width, this will cause the plots to appear distorted. In this case one can instead plot the velocity distribution of the quantities using flux_distribution, population_distribution, etc. To plot the velocity distribution of the density-matrix elements, use velocity_normalize(sol).

Table 1: Operators that can be applied to the solution of an LGS model
Description
population Fraction of total atomic population in each velocity group
total_population Total atomic population (should equal 1)
population_distribution Atomic population per unit velocity interval
level_population Population of each atomic level in each velocity group
total_level_population Total atomic population in each level
level_population_distribution Level population per unit velocity interval
flux Return flux on each transition from each velocity group
total_flux Total return flux
flux_distribution Return flux per unit velocity interval
velocity_sum Sum over velocity groups
velocity_normalize Normalize by velocity-group width

Check that the atomic population summed over all velocity groups is approximately 1:

model.total_population(sol).item()
0.9933933945227537

source

LGSSystem.adaptive_stationary_model

 LGSSystem.adaptive_stationary_model (mu, vg=6, max_weight=0.01)

Create a StationaryModel with narrower velocity bins in velocity regions with higher flux.

Type Default Details
mu Parameter values to use during velocity-group refinement
vg int 6 Initial velocity groups
max_weight float 0.01 Maximum fraction of the return flux from any one velocity group
Returns StationaryModel Steady-state LGS model with more velocity groups in regions that produce more return flux

Create a model with adaptively refined velocity groups using a particular value for the intensity parameter during refinement:

model = lgs.adaptive_stationary_model({'IntensitySI1': 1e3}, max_weight=0.2)

Solve and find total flux:

model.total_flux({'IntensitySI1': 1e3}).item()
91313.76877884821

Solve for the density matrix. The solution has density-matrix values for 17 velocity groups:

sol = model.solve({'IntensitySI1': 1e3})
sol
{Atomic velocity(17) ⨉ Density matrix (source)(4), }

Plot the velocity distribution of flux. Each point marks the center of a velocity group:

model.flux_distribution(sol).visualize(markers=True)

Velocity distribution of the density matrix:

model.velocity_normalize(sol).visualize()

Of the total population:

model.population_distribution(sol).visualize()

Of the level populations:

model.level_population_distribution(sol).visualize()

source

LGSSystem.instationary_model

 LGSSystem.instationary_model
                               (vg:Union[int,Iterable,pylgs.velocitygroups
                               .VelocityGroups]=6, T=1e-06,
                               num_values=100, initial_rho=None,
                               time_stepper=BDFTimeStepper())

Create an InstationaryModel for the LGS system dynamics.

Type Default Details
vg Union 6 Specification of velocity groups
T float 1e-06 Final time (seconds)
num_values int 100 Number of time step values to return
initial_rho NoneType None Initial density matrix. None means to use the thermal distribution
time_stepper BDFTimeStepper BDFTimeStepper() Solver to use
Returns InstationaryModel Model for the LGS system dynamics

An instationary model with 30 velocity groups:

model = lgs.instationary_model(
    vg=30, 
    T=1.e-4, 
    num_values=20
)

The BDF solver is efficient but can be very sensitive to the absolute and relative tolerance values. Set appropriate values for this problem:

pymor.basic.set_defaults({
    'pylgs.pymor.timestepping.cvode_solver_options.cvode_bdf_atol': 1e-3,
    'pylgs.pymor.timestepping.cvode_solver_options.cvode_bdf_rtol': 1e-5
})

Solve for a constant value of intensity:

sol = model.solve({'IntensitySI1': 1e3})

Visualize the total flux as a function of time:

model.total_flux(sol).visualize()

Plot the density matrix elements as a function of atomic velocity and animate as a function of time:

model.velocity_normalize(sol).visualize().update_layout(sliders=[dict(active=4)])

Animate the population distribution as a function of time:

model.population_distribution(sol).visualize()

Animate the level population distributions:

model.level_population_distribution(sol).visualize()

Set a shorter evolution time for the model:

model = model.with_(T=.3e-7, num_values=20)

Solve the model with a modulated intensity parameter:

sol = model.solve({'IntensitySI1': "5000.*sin(1.e8*t)**2"})

Visualize the total flux as a function of time:

model.total_flux(sol).visualize()

Visualize the density matrix elements:

model.velocity_normalize(sol).visualize()

Visualize the flux distribution:

model.flux_distribution(sol).visualize()
model.population_distribution(sol).visualize()

source

LGSSystem.stationary_floquet_model

 LGSSystem.stationary_floquet_model (mu, T, n_vector, nu:str='nu',
                                     n_operator=None, vg:Union[int,Iterabl
                                     e,pylgs.velocitygroups.VelocityGroups
                                     ]=6)

Return a StationaryFloquetModel for the Fourier coefficients of the periodic state of a modulated LGS system.

Type Default Details
mu Parameter specification for parameters modulated at a frequency nu
T List of time values to use for reconstruction
n_vector Number of terms in the system Fourier series
nu str nu Name of the frequency variable
n_operator NoneType None Number of terms in the operator Fourier series. None defaults to n_vector - 1
vg Union 6 Specification of velocity groups
Returns StationaryFloquetModel Model for the Fourier coefficients of the periodic LGS system

The StationaryFloquetModel solves for the periodic state of a modulated system after the transient dynamics have died out.

Build a stationary Floquet model for six Fourier harmonics of a system with sinusoidally modulated intensity:

model = lgs.stationary_floquet_model(
    {'IntensitySI1': "5000.*sin(nu*t)**2"},
    T=np.linspace(0, 1e-7, 20),
    n_vector=3,
    vg=30
)

Define values for the modulation frequency and light detuning:

mu = Mu(nu=1e8, DetuningHz1=0)

Solve for the periodic state. The solution contains 13 Fourier coefficients for each density-matrix element in each velocity group:

sol = model.solve(mu)
sol
{Fourier coefficient(7) ⨉ Atomic velocity(30) ⨉ Density matrix (source)(4), }

The real and imaginary parts of the Fourier coefficients of the time-dependent return flux:

model.total_flux(sol).visualize()

The total return flux reconstructed as a function of time:

model.reconstructed_total_flux(sol, mu).real.visualize()

The real and imaginary parts of the Fourier coefficients of the real and imaginary parts of the density-matrix elements:

model.velocity_normalize(mu).visualize()

The real and imaginary parts of the density-matrix elements reconstructed as a function of time:

model.velocity_normalize(model.reconstruct(mu)).real.visualize()